/**
 * 
 */
package org.swing.utility.jai.component;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.image.renderable.ParameterBlock;
import java.io.File;

import javax.media.jai.InterpolationBilinear;
import javax.media.jai.InterpolationNearest;
import javax.media.jai.JAI;
import javax.media.jai.PlanarImage;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

import com.sun.media.jai.widget.DisplayJAI;

/**
 * @author lqnhu
 *
 */
@SuppressWarnings("serial")
public class ImagePanel extends JPanel {
	private PlanarImage originalImage = null;
	private PlanarImage workingImage = null;
	private PlanarImage rotatedoriginalImage = null;
	private DisplayJAI dj = null;
	private File imageFile = null;
	private float currentZoomLevel;
	private boolean imageIsRotated;

	public ImagePanel() {
		super();
		dj = new DisplayJAI();
		this.setBackground(Color.darkGray);
		this.imageIsRotated = false;
	}

	public ImagePanel(File f) {
		super();
		imageFile = f;
		originalImage = workingImage = JAI.create("fileload",
				imageFile.getPath());
		dj = new DisplayJAI(workingImage);
		this.imageIsRotated = false;
		this.setZoomLevel(1.0f);
		this.add(dj);
		this.setAutoscrolls(true);
		this.setBackground(Color.darkGray);
	}

	public boolean imageIsLoaded() {
		boolean loaded = false;
		if (dj.getHeight() == 0)
			loaded = true;
		return loaded;
	}

	public void setZoomLevel(float level) {
		this.currentZoomLevel = level;
		this.scaleimage(this.currentZoomLevel);
	}

	public void setimage(File f) {
		imageFile = f;
		originalImage = workingImage = JAI.create("fileload",
				imageFile.getAbsolutePath());
		this.setZoomLevel(1.0f);
		this.changeImage(workingImage);
	}

	public float getZoomLevel() {
		return this.currentZoomLevel;
	}

	public void invertimage() {
		PlanarImage invertedimage = JAI.create("invert", workingImage);
		this.changeImage(invertedimage);
	}

	public void scaleimage(float scaleFactor) {
		this.currentZoomLevel = scaleFactor;
		ParameterBlock pb = new ParameterBlock();
		if (imageIsRotated)
			pb.addSource(rotatedoriginalImage);
		else
			pb.addSource(originalImage);
		pb.add(scaleFactor); // scale x
		pb.add(scaleFactor); // scale y
		pb.add(0.0f); // pic translation x
		pb.add(0.0f); // pic translation y
		pb.add(new InterpolationNearest());
		PlanarImage scaledImage = JAI.create("scale", pb);
		this.setLocation(0, 0);
		this.changeImage(scaledImage);
	}

	private void rescale() {
		ParameterBlock pb = new ParameterBlock();
		try {
			pb.addSource(rotatedoriginalImage);
			pb.add(this.currentZoomLevel);
			pb.add(this.currentZoomLevel);
			pb.add(0.0f);
			pb.add(0.0f);
			pb.add(new InterpolationNearest());
			PlanarImage scaledImage = JAI.create("scale", pb);
			this.setLocation(0, 0);
			this.changeImage(scaledImage);
		} catch (Exception e) {
			JOptionPane.showMessageDialog(null, e.getMessage());
		}
	}

	public void rotateImage(int degreesToRotate) {
		float angle = (float) Math.toRadians(degreesToRotate);
		float centerX;
		float centerY;
		ParameterBlock pb = new ParameterBlock();
		if (rotatedoriginalImage == null) {
			pb.addSource(originalImage);
			centerX = (float) (this.getOriginalDimensions().getWidth()) / 2f;
			centerY = (float) (this.getOriginalDimensions().getHeight()) / 2f;
		} else {
			pb.addSource(rotatedoriginalImage);
			centerX = (float) (this.getRotatedOriginalDimensions().getWidth()) / 2f;
			centerY = (float) (this.getRotatedOriginalDimensions().getHeight()) / 2f;
		}
		pb.add(centerX);
		pb.add(centerY);
		pb.add(angle);
		pb.add(new InterpolationBilinear());
		PlanarImage rotatedImage = JAI.create("rotate", pb);
		this.rotatedoriginalImage = rotatedImage;
		this.rescale();
		this.imageIsRotated = true;
	}

	private void changeImage(PlanarImage newImage) {
		if (originalImage == null) {
			originalImage = newImage;
		}
		workingImage = newImage;
		this.remove(dj);
		dj.set(workingImage);
		this.add(dj);
		this.validate();
		this.repaint();
	}

	public Dimension getOriginalDimensions() {
		return new Dimension(originalImage.getWidth(),
				originalImage.getHeight());
	}

	public Dimension getRotatedOriginalDimensions() {
		return new Dimension(rotatedoriginalImage.getWidth(),
				rotatedoriginalImage.getHeight());
	}

	public Dimension getCurrentDimesions() {
		return new Dimension(workingImage.getWidth(), workingImage.getHeight());
	}
}
